﻿#include "tars2cpp.h"
#include "util/tc_md5.h"
#include "util/tc_file.h"
#include "util/tc_common.h"
#include <string>

using namespace std;

#define TAB g_parse->getTab()
#define INC_TAB g_parse->incTab()
#define DEL_TAB g_parse->delTab()

//////////////////////////////////////////////////////////////////////////////////

string getDesc(const string& desc, const std::string& key) {
    string ldesc;
    if (!desc.empty() && desc.find("desc:") != desc.npos) {
        auto pos = desc.find("desc:");
        if (pos != desc.npos) {
            ldesc = desc.substr(pos + 5);
        }
        pos = ldesc.find("[");
        if (pos != ldesc.npos) {
            ldesc = ldesc.substr(pos + 1);
        }
        pos = ldesc.find("]");
        if (pos != ldesc.npos) {
            ldesc = ldesc.substr(0, pos);
        }
        if(!key.empty()) {
            pos = ldesc.find(key);
            if (pos != ldesc.npos) {
                ldesc = ldesc.substr(pos + key.length());
                pos = ldesc.find("\"");
                if (pos != ldesc.npos) {
                    ldesc = ldesc.substr(pos + 1);
                }
                pos = ldesc.find("\"");
                if (pos != ldesc.npos) {
                    ldesc = ldesc.substr(0, pos);
                }
            } else {
                ldesc.clear();
            }
        }
    }
    return ldesc;
}

//////////////////////////////////////////////////////////////////////////////////
//
Tars2Cpp::Tars2Cpp()
    : _checkDefault(false)
    , _onlyStruct(false)
    , _bJsonSupport(true)
    , _namespace("tars")
    , _tarsMaster(false) {

}

string Tars2Cpp::writeToXml(const TypeIdPtr& pPtr) const {
    ostringstream s;
    if (EnumPtr::dynamicCast(pPtr->getTypePtr())) {
        s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace +
          "::XmlOutput::writeXml((" + _namespace + "::Int32)" << pPtr->getId() << ", _cdata_format);" << endl;
    } else if (pPtr->getTypePtr()->isArray()) {
        s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace +
          "::XmlOutput::writeXml((const " << tostr(pPtr->getTypePtr()) << " *)" << pPtr->getId() << "Len"  << ");" << endl;
    } else if (pPtr->getTypePtr()->isPointer()) {
        s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace +
          "::XmlOutput::writeXml((const " << tostr(pPtr->getTypePtr()) << " )" << pPtr->getId() << "Len"  << ");" << endl;
    } else {
        MapPtr mPtr = MapPtr::dynamicCast(pPtr->getTypePtr());
        VectorPtr vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr());
        if (!_checkDefault || pPtr->isRequire() || (!pPtr->hasDefault() && !mPtr && !vPtr)) {
            BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
            if (pPtr->getTypePtr()->isSimple() || (bPtr && bPtr->kind() == Builtin::KindString)) {
                s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::XmlOutput::writeXml(" << pPtr->getId() << ", _cdata_format);" << endl;
            } else {
                s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::XmlOutput::writeXml(" << pPtr->getId() << ");" << endl;
            }
        } else {
            string sDefault = pPtr->def();
            BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
            if (bPtr && bPtr->kind() == Builtin::KindString) {
                sDefault = "\"" + TC_Common::replace(pPtr->def(), "\"", "\\\"") + "\"";
            }

            if (mPtr || vPtr) {
                s << TAB << "if (" << pPtr->getId() << ".size() > 0) {" << endl;
            } else {
                s << TAB << "if (" << pPtr->getId() << " != " << sDefault << ") {" << endl;
            }
            INC_TAB;
            s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::XmlOutput::writeXml(" << pPtr->getId() << ");" << endl;
            DEL_TAB;
            s << TAB << "}" << endl;
        }
    }
    return s.str();
}

string Tars2Cpp::readFromXml(const TypeIdPtr& pPtr, bool bIsRequire) const {
    ostringstream s;
    if (EnumPtr::dynamicCast(pPtr->getTypePtr())) {
        s << TAB << "tars::XmlInput::readXml((tars::Int32&)" << pPtr->getId() << ", pObj->value[\"" << pPtr->getId() << "\"]";
    } else if (pPtr->getTypePtr()->isArray()) {
        s << TAB << "tars::XmlInput::readXml(" << pPtr->getId() << "Len" << ", pObj->value[\"" << pPtr->getId() << "\"]" << getSuffix(pPtr);
    } else if (pPtr->getTypePtr()->isPointer()) {
        // "not support";
    } else {
        s << TAB << "tars::XmlInput::readXml(" << pPtr->getId() << ",pObj->value[\"" << pPtr->getId() << "\"]";
    }
    s << ", " << ((pPtr->isRequire() && bIsRequire) ? "true" : "false") << ");" << endl;
    return s.str();
}

string Tars2Cpp::writeToSql(const TypeIdPtr& pPtr) const {
    ostringstream s;
    if (EnumPtr::dynamicCast(pPtr->getTypePtr())) {
        s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_INT, tars::TC_Common::tostr(" << pPtr->getId() << "));" << endl;
    }

    BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
    if (bPtr) {
        switch (bPtr->kind()) {
            case Builtin::KindBool:
            case Builtin::KindByte:
            case Builtin::KindShort:
            case Builtin::KindInt:
            case Builtin::KindLong:
                s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_INT, tars::TC_Common::tostr(" << pPtr->getId() << "));" << endl;
                break;
            case Builtin::KindFloat:
            case Builtin::KindDouble:
                s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_STR, tars::TC_Common::tostr(" << pPtr->getId() << "));" << endl;
                break;
            case Builtin::KindString:
                s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_STR, tars::TC_Common::trim(" << pPtr->getId() << "));" << endl;
                break;
            default:
                break;
        }
    } else if (!pPtr->getTypePtr()->isSimple()) {
        s << TAB << "_mycols[\"" << pPtr->getId()
          << "\"] = make_pair(tars::TC_Mysql::DB_STR, tars::TC_Json::writeValue(tars::JsonOutput::writeJson(" << pPtr->getId() << ")));" << endl;
    }

    return s.str();
}

string Tars2Cpp::readFromSql(const TypeIdPtr& pPtr, bool bIsRequire) const {
    ostringstream s;
    EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr());
    if (ePtr) {
        s << TAB << pPtr->getId() << " = (" << ePtr->getSid() << ")TC_Common::strto<tars::Int32>(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
    }

    BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
    if (bPtr) {
        switch (bPtr->kind()) {
            case Builtin::KindBool:
                s << TAB << pPtr->getId() << " = TC_Common::strto<tars::Bool>(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
                break;
            case Builtin::KindByte:
                s << TAB << pPtr->getId() << " = TC_Common::strto<tars::" << (bPtr->isUnsigned() ? "UInt8" : "Char")
                  << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
                break;
            case Builtin::KindShort:
                s << TAB << pPtr->getId() << " = TC_Common::strto<tars::" << (bPtr->isUnsigned() ? "UInt16" : "Short")
                  << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
                break;
            case Builtin::KindInt:
                s << TAB << pPtr->getId() << " = TC_Common::strto<tars::" << (bPtr->isUnsigned() ? "UInt32" : "Int32")
                  << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
                break;
            case Builtin::KindLong:
                s << TAB << pPtr->getId() << " = TC_Common::strto<tars::" << (bPtr->isUnsigned() ? "UInt64" : "Int64")
                  << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
                break;
            case Builtin::KindFloat:
                s << TAB << pPtr->getId() << " = TC_Common::strto<tars::Float>(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
                break;
            case Builtin::KindDouble:
                s << TAB << pPtr->getId() << " = TC_Common::strto<tars::Double>(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
                break;
            case Builtin::KindString:
                s << TAB << pPtr->getId() << " = TC_Common::trim(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
                break;
            default:
                break;
        }
    } else if (!pPtr->getTypePtr()->isSimple()) {
        s << TAB << "tars::JsonInput::readJson(" << pPtr->getId() << ", tars::TC_Json::getValue(_mysrd[\"" << pPtr->getId() << "\"]), false);" << endl;
    }
    return s.str();
}

string Tars2Cpp::writeToJson(const TypeIdPtr& pPtr) const {
    ostringstream s;

    bool skipbd = false;
    if(_bMarkSupport) {
        auto sdesc = pPtr->getLDesc();
        auto ldesc = getDesc(sdesc, "json:");
        if(ldesc.empty()) {
            ldesc = getDesc(sdesc, "gorm:");
        }
        skipbd = (ldesc == "-");
    }
    if(skipbd) {
        s << TAB << "if(!todb) {" << endl;
        INC_TAB;
    }

    if (EnumPtr::dynamicCast(pPtr->getTypePtr())) {
        s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace +
          "::JsonOutput::writeJson((" + _namespace + "::Int32)" << pPtr->getId() << ");" << endl;
    } else if (pPtr->getTypePtr()->isArray()) {
        s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::JsonOutput::writeJson((const "
          << tostr(pPtr->getTypePtr()) << " *)" << pPtr->getId() << ", " << pPtr->getId() << "Len"  << ");" << endl;
    } else if (pPtr->getTypePtr()->isPointer()) {
        s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::JsonOutput::writeJson((const "
          << tostr(pPtr->getTypePtr()) << " )" << pPtr->getId() << ", " << pPtr->getId() << "Len"  << ");" << endl;
    } else {
        MapPtr mPtr = MapPtr::dynamicCast(pPtr->getTypePtr());
        VectorPtr vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr());

        // 对于json， 不检测默认值
        if (true || !_checkDefault || pPtr->isRequire() || (!pPtr->hasDefault() && !mPtr && !vPtr)) {
            s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace +
              "::JsonOutput::writeJson(" << pPtr->getId() << ");" << endl;
        } else {
            auto sDefault = pPtr->def();
            auto bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
            if (bPtr && bPtr->kind() == Builtin::KindString) {
                sDefault = "\"" + tars::TC_Common::replace(pPtr->def(), "\"", "\\\"") + "\"";
            }

            if (mPtr || vPtr) {
                s << TAB << "if (" << pPtr->getId() << ".size() > 0) {" << endl;
            } else if (bPtr && (bPtr->kind() == Builtin::KindFloat || bPtr->kind() == Builtin::KindDouble)) {
                s << TAB << "if (!tars::TC_Common::equal(" << pPtr->getId() << "," << sDefault << ")) {" << endl;
            } else {
                s << TAB << "if (" << pPtr->getId() << " != " << sDefault << ") {" << endl;
            }
            INC_TAB;
            s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace +
              "::JsonOutput::writeJson(" << pPtr->getId() << ");" << endl;
            DEL_TAB;
            s << TAB << "}" << endl;
        }
    }

    if(skipbd) {
        DEL_TAB;
        s << TAB << "}" << endl;
    }
    return s.str();
}

string Tars2Cpp::readFromJson(const TypeIdPtr& pPtr, bool bIsRequire) const {
    ostringstream s;
    if (pPtr->getTypePtr()->isArray()) {
        s << TAB << _namespace + "::JsonInput::readJson(" << pPtr->getId() << ", " << "sizeof(" + pPtr->getId() + ")"
          << ", " << pPtr->getId() << "Len" << ", pObj->value[\"" << pPtr->getId() << "\"]";
    } else if (pPtr->getTypePtr()->isPointer()) {
        s << TAB << "not support";
    } else {
        s << TAB << _namespace + "::JsonInput::readJson(" << pPtr->getId() << ",pObj->value[\"" << pPtr->getId() << "\"]";
    }
    s << ", " << ((pPtr->isRequire() && bIsRequire) ? "true" : "false") << ");" << endl;
    return s.str();
}

string Tars2Cpp::writeTo(const TypeIdPtr& pPtr) const {
    ostringstream s;
    if (EnumPtr::dynamicCast(pPtr->getTypePtr())) {
        s << TAB << "_os.write((" + _namespace + "::Int32)" << pPtr->getId() << ", " << pPtr->getTag() << ");" << endl;
    } else if (pPtr->getTypePtr()->isArray()) {
        s << TAB << "_os.write((const " << tostr(pPtr->getTypePtr()) << " *)" << pPtr->getId() << ", " << pPtr->getId()
          << "Len" << ", " << pPtr->getTag() << ");" << endl;
    } else if (pPtr->getTypePtr()->isPointer()) {
        s << TAB << "_os.write((const " << tostr(pPtr->getTypePtr()) << ")" << pPtr->getId() << ", " << pPtr->getId()
          << "Len" << ", " << pPtr->getTag() << ");" << endl;
    } else {
        auto mPtr = MapPtr::dynamicCast(pPtr->getTypePtr());
        auto vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr());
        if (!_checkDefault || pPtr->isRequire() || (!pPtr->hasDefault() && !mPtr && !vPtr)) {
            s << TAB << "_os.write(" << pPtr->getId() << ", " << pPtr->getTag() << ");" << endl;
        } else {
            auto sDefault = pPtr->def();
            auto bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
            if (bPtr && bPtr->kind() == Builtin::KindString) {
                sDefault = "\"" + tars::TC_Common::replace(pPtr->def(), "\"", "\\\"") + "\"";
            }

            if (mPtr || vPtr) {
                s << TAB << "if (" << pPtr->getId() << ".size() > 0) {" << endl;
            } else {
                s << TAB << "if (" << pPtr->getId() << " != " << sDefault << ") {" << endl;
            }
            INC_TAB;
            s << TAB << "_os.write(" << pPtr->getId() << ", " << pPtr->getTag() << ");" << endl;
            DEL_TAB;
            s << TAB << "}" << endl;
        }
    }
    return s.str();
}

string Tars2Cpp::readFrom(const TypeIdPtr& pPtr, bool bIsRequire) const {
    ostringstream s;
    if (EnumPtr::dynamicCast(pPtr->getTypePtr())) {
        //枚举强制类型转换在O2编译选项情况下会告警
        string tmp = _namespace + "::Int32 eTemp" + TC_Common::tostr(pPtr->getTag()) + generateInitValue(pPtr);
        s << TAB << tmp << endl;
        s << TAB << "_is.read(eTemp" << TC_Common::tostr(pPtr->getTag());
    } else if (pPtr->getTypePtr()->isArray()) {
        s << TAB << "_is.read(" << pPtr->getId() << ", " << "sizeof(" + pPtr->getId() + ")" << ", " << pPtr->getId() << "Len";
    } else if (pPtr->getTypePtr()->isPointer()) {
        s << TAB << pPtr->getId() << " = (" << tostr(pPtr->getTypePtr()) << ")_is.cur();" << endl;
        s << TAB << "_is.read(" << pPtr->getId() << ", _is.left(), " << pPtr->getId() << "Len";
    } else {
        s << TAB << "_is.read(" << pPtr->getId();
    }
    s << ", " << pPtr->getTag() << ", " << ((pPtr->isRequire() && bIsRequire) ? "true" : "false") << ");" << endl;

    if (EnumPtr::dynamicCast(pPtr->getTypePtr())) {
        s << TAB << pPtr->getId() << " = (" << tostr(pPtr->getTypePtr()) << ")eTemp" << TC_Common::tostr(pPtr->getTag()) << ";" << endl;
    }
    if (pPtr->getTypePtr()->isPointer()) {
        s << TAB << "_is.mapBufferSkip(" << pPtr->getId() << "Len);" << endl;
    }
    return s.str();
}

string Tars2Cpp::display(const TypeIdPtr& pPtr) const {
    ostringstream s;
    if (EnumPtr::dynamicCast(pPtr->getTypePtr())) {
        s << TAB << "_ds.display((" + _namespace + "::Int32)" << pPtr->getId() << ",\"" << pPtr->getId() << "\");" << endl;;
    } else if (pPtr->getTypePtr()->isArray() || pPtr->getTypePtr()->isPointer()) {
        s << TAB << "_ds.display(" << pPtr->getId() << ", " << pPtr->getId() << "Len" << ",\"" << pPtr->getId() << "\");" << endl;
    } else {
        s << TAB << "_ds.display(" << pPtr->getId() << ",\"" << pPtr->getId() << "\");" << endl;;
    }
    return s.str();
}

string Tars2Cpp::displaySimple(const TypeIdPtr& pPtr, bool bSep) const {
    ostringstream s;
    if (EnumPtr::dynamicCast(pPtr->getTypePtr())) {
        s << TAB << "_ds.displaySimple((" + _namespace + "::Int32)" << pPtr->getId() << ", "
          << (bSep ? "true" : "false") << ");" << endl;
    } else if (pPtr->getTypePtr()->isArray()) {
        s << TAB << "_ds.displaySimple(" << pPtr->getId() << ", " << pPtr->getId() << "Len" << ","
          << (bSep ? "true" : "false") << ");" << endl;
    } else if (pPtr->getTypePtr()->isPointer()) {
        s << TAB << "_ds.displaySimple(";
        s << (bSep ? "" : ("(const " + tostr(pPtr->getTypePtr()) + ")"));
        s << pPtr->getId() << ", " << pPtr->getId() << "Len" << "," << (bSep ? "true" : "false") << ");" << endl;
    } else {
        s << TAB << "_ds.displaySimple(" << pPtr->getId() << ", "
          << (bSep ? "true" : "false") << ");" << endl;
    }
    return s.str();
}


string Tars2Cpp::generateCollection(const TypeIdPtr& pPtr, bool bSep) const {
    ostringstream s;
    if (pPtr->getTypePtr()->isArray()) {
        s << TAB << "_jj.generateCollection(" << "\"" << pPtr->getId() <<  "\""  << ", " << pPtr->getId() << ", " << pPtr->getId() << "Len"
          << ");" << "\n" << (bSep ? TAB + "_jj.append(\",\", false);" : "") << endl;
    } else {
        s << TAB << "_jj.generateCollection(" << "\"" << pPtr->getId() <<  "\"" << ", " << pPtr->getId()
          << ");" << "\n" << (bSep ? TAB + "_jj.append(\",\", false);" : "") << endl;
    }
    return s.str();
}


/*******************************获取定长数组坐标********************************/
int Tars2Cpp::getSuffix(const TypeIdPtr& pPtr) const {
    auto bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
    if (bPtr && bPtr->kind() == Builtin::KindString && bPtr->isArray()) {
        return bPtr->getSize();
    }
    auto vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr());
    if (vPtr && vPtr->isArray()) {
        return vPtr->getSize();
    }
    return -1;
}

/*******************************定长数组坐标********************************/

string Tars2Cpp::toStrSuffix(const TypeIdPtr& pPtr) const {
    ostringstream s;
    auto i = getSuffix(pPtr);
    if (i >= 0) {
        s << "[" << i << "]";
    }
    return s.str();
}
/*******************************BuiltinPtr********************************/

string Tars2Cpp::tostr(const TypePtr& pPtr, bool bnspace) const {
    auto bPtr = BuiltinPtr::dynamicCast(pPtr);
    if (bPtr) {
        return tostrBuiltin(bPtr, bnspace);
    }
    auto vPtr = VectorPtr::dynamicCast(pPtr);
    if (vPtr) {
        return tostrVector(vPtr);
    }
    auto mPtr = MapPtr::dynamicCast(pPtr);
    if (mPtr) {
        return tostrMap(mPtr);
    }
    auto sPtr = StructPtr::dynamicCast(pPtr);
    if (sPtr) {
        return tostrStruct(sPtr);
    }
    auto ePtr = EnumPtr::dynamicCast(pPtr);
    if (ePtr) {
        return tostrEnum(ePtr);
    }
    if (!pPtr) {
        return "void";
    }
    return "";
}

string Tars2Cpp::tostrBuiltin(const BuiltinPtr& pPtr, bool bnspace) const {
    string s;
    switch (pPtr->kind()) {
        case Builtin::KindBool:
            s = bnspace ? _namespace + "::Bool" : "Bool";
            break;
        case Builtin::KindByte:
            s = bnspace ? _namespace + "::Char" : "Char";
            break;
        case Builtin::KindShort: // 为了兼容java无unsigned, 编解码时把tars文件中 unsigned char 对应到short c++中需要还原回来
            if (pPtr->isUnsigned()) {
                s = bnspace ? _namespace + "::UInt8" : "UInt8";
            } else {
                s = bnspace ? _namespace + "::Short" : "Short";
            }
            break;
        case Builtin::KindInt:
            if (pPtr->isUnsigned()) {
                s = bnspace ? _namespace + "::UInt16" : "UInt16";
            } else {
                s = bnspace ? _namespace + "::Int32" : "Int32";
            }
            break;
        case Builtin::KindLong:
            if (pPtr->isUnsigned()) {
                s = bnspace ? _namespace + "::UInt32" : "UInt32";
            } else {
                s = bnspace ? _namespace + "::Int64" : "Int64";
            }
            break;
        case Builtin::KindFloat:
            s = bnspace ? _namespace + "::Float" : "Float";
            break;
        case Builtin::KindDouble:
            s = bnspace ? _namespace + "::Double" : "Double";
            break;
        case Builtin::KindString:
            if (pPtr->isArray()) {
                s = bnspace ? _namespace + "::Char" : "Char"; // char a [8];
            } else {
                s = bnspace ? "std::string" : "String";
            }
            break;
        case Builtin::KindVector:
            s = bnspace ? "std::vector" : "Vector";
            break;
        case Builtin::KindMap:
            s = bnspace ? "std::map" : "Map";
            break;
        default:
            assert(false);
            break;
    }
    return s;
}
/*******************************VectorPtr********************************/
string Tars2Cpp::tostrVector(const VectorPtr& pPtr) const {
    if (pPtr->isArray()) { // 数组类型
        return tostr(pPtr->getTypePtr());
    }
    if (pPtr->isPointer()) { // 指针类型
        return tostr(pPtr->getTypePtr()) + " *";
    }

    string s = Builtin::builtinTable[Builtin::KindVector] + string("<") + tostr(pPtr->getTypePtr());
    if (MapPtr::dynamicCast(pPtr->getTypePtr()) || VectorPtr::dynamicCast(pPtr->getTypePtr())) {
        s += " >";
    } else {
        s += ">";
    }
    return s;
}
/*******************************MapPtr********************************/
string Tars2Cpp::tostrMap(const MapPtr& pPtr) const {
    string s = Builtin::builtinTable[Builtin::KindMap] + string("<") + tostr(pPtr->getLeftTypePtr()) + ", " + tostr(pPtr->getRightTypePtr());
    if (MapPtr::dynamicCast(pPtr->getRightTypePtr()) || VectorPtr::dynamicCast(pPtr->getRightTypePtr())) {
        s += " >";
    } else {
        s += ">";
    }
    return s;
}

/*******************************StructPtr********************************/
string Tars2Cpp::tostrStruct(const StructPtr& pPtr) const {
    return pPtr->getSid();
}

string Tars2Cpp::MD5(const StructPtr& pPtr) const {
    string s;
    auto& member = pPtr->getAllMemberPtr();
    for (size_t j = 0; j < member.size(); j++) {
        s += "_" + tostr(member[j]->getTypePtr());
    }
    return "\"" + tars::TC_MD5::md5str(s) + "\"";
}

/////////////////////////////////////////////////////////////////////
string Tars2Cpp::tostrEnum(const EnumPtr& pPtr) const {
    return pPtr->getSid();
}
///////////////////////////////////////////////////////////////////////
string Tars2Cpp::generateH(const StructPtr& pPtr, const string& namespaceId) const {
    ostringstream s;

    s << TAB << "struct " << pPtr->getId() << " : public " + _namespace + "::TarsStructBase {" << endl;
    s << TAB << "public:" << endl;

    INC_TAB;

    s << TAB << "static std::string className() {" << endl;
    INC_TAB;
    s << TAB << "return " << "\"" << namespaceId << "." << pPtr->getId() << "\"" << ";" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;
    s << TAB << "static std::string MD5() {" << endl;
    INC_TAB;
    s << TAB << "return " << MD5(pPtr) << ";" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    ////////////////////////////////////////////////////////////
    //定义缺省构造函数
    s << TAB << pPtr->getId() << "() {" << endl;
    INC_TAB;
    s << TAB << "clear();" << endl;
    auto& member = pPtr->getAllMemberPtr();

    DEL_TAB;
    s << TAB << "}" << endl;

    if(_bMarkSupport) {
        //拷贝构造函数
        s << TAB << pPtr->getId() << "(const " << pPtr->getId() << "&r) {" << endl;
        INC_TAB;
        s << TAB << "copy(r);" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;

        //拷贝函数
        s << TAB << pPtr->getId() << "& operator=(const " << pPtr->getId() << "&r) {" << endl;
        INC_TAB;
        s << TAB << "copy(r); return *this;" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;

        //拷贝操作
        s << TAB << "void copy(const " << pPtr->getId() << "&r) {" << endl;
        INC_TAB;
        for (size_t j = 0; j < member.size(); j++) {
            auto& pmbr = member[j];
            if (!pmbr) {
                continue;
            }
            if (pmbr->getTypePtr()->isArray() || pmbr->getTypePtr()->isPointer()) { //数组类型、指针类型
                s << TAB << "memcpy(this->" << pmbr->getId() << ", r." << pmbr->getId() << ", this->" << pmbr->getId() << "Len);" << endl;
                continue;
            }
            auto ldesc = pmbr->getLDesc();
            if(ldesc.find("desc:") != ldesc.npos && ldesc.find("2tars:") != ldesc.npos && ldesc.find("atomic") != ldesc.npos) {
                s << TAB << "this->" << pmbr->getId() << " = r." << pmbr->getId() << ".load();" << endl;
                continue;
            }
            s << TAB << "this->" << pmbr->getId() << " = r." << pmbr->getId() << ";" << endl;
        }
        s << TAB << "this->_chgmark = r._chgmark;" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;
    }

    //resetDefault()函数
    s << TAB << "void clear() {" <<  endl;
    INC_TAB;

    member = pPtr->getAllMemberPtr();
    for (size_t j = 0; j < member.size(); j++) {
        auto pmbr = member[j];
        if (!pmbr) {
            continue;
        }
        if (pmbr->getTypePtr()->isArray()) {
            s << TAB << pmbr->getId() << "Len = 0;" << endl;
            auto vPtr = VectorPtr::dynamicCast(pmbr->getTypePtr());
            if (vPtr) {
                auto bPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr());
                if (bPtr &&  bPtr->kind() != Builtin::KindString) { //非内建类型或者string 类型不能memset
                    s << TAB << "memset(" << pmbr->getId() << ", 0, " << "sizeof(" << pmbr->getId() << "));" << endl;
                }
            }
            continue;
        }

        if (pmbr->getTypePtr()->isPointer()) {
            s << TAB << pmbr->getId() << "Len = 0;" << endl;
            s << TAB << pmbr->getId() << " = nullptr;" << endl;
            continue;
        }

        if (pmbr->hasDefault()) {
            auto bPtr  = BuiltinPtr::dynamicCast(pmbr->getTypePtr());
            if (bPtr && bPtr->kind() == Builtin::KindString) { // string值要转义
                string tmp = tars::TC_Common::replace(pmbr->def(), "\"", "\\\"");
                s << TAB << pmbr->getId() << " = \"" << tmp << "\";" << endl;
            } else {
                s << TAB << pmbr->getId() << " = " << pmbr->def() << ";" << endl;
            }
        } else {
            //没有提供初始值才会走到这里,提供枚举类型初始化值
            auto ePtr = EnumPtr::dynamicCast(pmbr->getTypePtr());
            if (ePtr) {
                auto& eMember = ePtr->getAllMemberPtr();
                if (eMember.size() > 0) {
                    auto sid = ePtr->getSid();
                    s << TAB << pmbr->getId() << " = " << sid.substr(0, sid.find_first_of("::")) << "::" << eMember[0]->getId() << ";" << endl;
                }
            } else if(_bMarkSupport) {
                s << TAB << pmbr->getId() << ".clear();" << endl;
            }
        }
    }

    if (_bMarkSupport) {
        s << TAB << "_chgmark.clear();" << endl;
    }

    DEL_TAB;
    s << TAB << "}" << endl;

    s << TAB << "template<typename WriterT>" << endl;
    s << TAB << "void writeTo(" + _namespace + "::TarsOutputStream<WriterT>& _os) const {" << endl;
    INC_TAB;
    for (size_t j = 0; j < member.size(); j++) {
        s << writeTo(member[j]);
    }

    DEL_TAB;
    s << TAB << "}" << endl;

    ///////////////////////////////////////////////////////////
    s << TAB << "template<typename ReaderT>" << endl;
    s << TAB << "void readFrom(" + _namespace + "::TarsInputStream<ReaderT>& _is) {" << endl;
    INC_TAB;
    s << TAB << "clear();" << endl;
    for (size_t j = 0; j < member.size(); j++) {
        s << readFrom(member[j]);
    }

    DEL_TAB;
    s << TAB << "}" << endl;

    if (_bJsonSupport) {
        s << TAB << "tars::JsonValueObjPtr writeToJson(" << (_bMarkSupport ? "bool todb = false" : "") << ") const {" << endl;
        INC_TAB;
        s << TAB << "auto p = new tars::JsonValueObj();" << endl;
        for (size_t j = 0; j < member.size(); j++) {
            s << writeToJson(member[j]);
        }
        s << TAB << "return p;" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;

        s << TAB << "std::string writeToJsonString(" << (_bMarkSupport ? "bool todb = false" : "") <<") const {" << endl;
        INC_TAB;
        s << TAB << "return tars::TC_Json::writeValue(writeToJson(" << (_bMarkSupport ? "todb" : "") << "));" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;

        s << TAB << "bool readFromJson(const tars::JsonValuePtr& p, bool isRequire = true) {" << endl;
        INC_TAB;
        s << TAB << "clear();" << endl;
        s << TAB << "if(nullptr == p.get() || p->getType() != tars::eJsonTypeObj) {" << endl;
        INC_TAB;
        s << TAB << "return false;" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;
        s << TAB << "auto pObj = tars::JsonValueObjPtr::dynamicCast(p);" << endl;
        for (size_t j = 0; j < member.size(); j++) {
            s << readFromJson(member[j]);
        }
        s << TAB << "return true;" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;

        s << TAB << "bool readFromJsonString(const std::string& str) {" << endl;
        INC_TAB;
        s << TAB << "return readFromJson(tars::TC_Json::getValue(str));" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;
    }

    s << TAB << "std::ostream& display(std::ostream& _os, int _level = 0) const {" << endl;
    INC_TAB;
    s << TAB << _namespace + "::TarsDisplayer _ds(_os, _level);" << endl;

    for (size_t j = 0; j < member.size(); j++) {
        s << display(member[j]);
    }
    s << TAB << "return _os;" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    s << TAB << "std::ostream& displaySimple(std::ostream& _os, int _level = 0) const {" << endl;
    INC_TAB;
    s << TAB << _namespace + "::TarsDisplayer _ds(_os, _level);" << endl;

    for (size_t j = 0; j < member.size(); j++) {
        s << displaySimple(member[j], (j != member.size() - 1 ? true : false));
    }
    s << TAB << "return _os;" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    //定义==操作
    s << TAB << "inline bool operator==(const " << pPtr->getId() << "&r) const {" << endl;
    INC_TAB;
    s << TAB << "return ";
    for (size_t j = 0; j < member.size(); j++) {
        auto& pmbr = member[j];
        if (!pmbr) {
            continue;
        }
        if (pmbr->getTypePtr()->isArray() || pmbr->getTypePtr()->isPointer()) { //数组类型、指针类型
            s << "!memcmp(this->" << pmbr->getId() << ", r." << pmbr->getId() << ", this->" << pmbr->getId() << "Len)";
        } else {
            s << "this->" << pmbr->getId() << " == r." << pmbr->getId();
        }
        if (j != member.size() - 1) {
            s << " && ";
        }
    }
    s << ";" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    DEL_TAB;
    s << TAB << "public:" << endl;
    INC_TAB;

    //定义成员变量
    int maxtag = 0;
    map<string, string> _2tars;
    for (size_t j = 0; j < member.size(); j++) {
        auto& pmbr = member[j];
        if (!pmbr) {
            continue;
        }
        if (pmbr->getTypePtr()->isArray() || pmbr->getTypePtr()->isPointer()) { //数组类型、指针类型需要定义长度
            s << TAB << _namespace + "::" << "UInt32 " << pmbr->getId() << "Len" << ";" << endl;
        }
        if (_bMarkSupport) {
            _2tars.clear();
            auto ldesc = getDesc(pmbr->getLDesc(), "2tars:");
            if (!ldesc.empty()) {
                auto sarr = tars::TC_Common::sepstr<std::string>(ldesc, ";");
                if (!sarr.empty()) {
                    for (auto& skey : sarr) {
                        auto skeys = tars::TC_Common::sepstr<std::string>(skey, ":");
                        if (skeys.size() > 0) {
                            _2tars[skeys[0]] = (skeys.size() > 1 ? skeys[1] : "");
                        }
                    }
                }
            }
            auto ntag = pmbr->getTag() + 1;
            if (ntag > maxtag) {
                maxtag = ntag;
            }
            auto stp = tostr(pmbr->getTypePtr(), false);

            string smacro = "TARS_MBR";
            if (_2tars.find("atomic") != _2tars.end()) {
                smacro = "TARS_MBR_S";
                stp = "ATM_" + stp + ", " + _namespace + "::" + stp;
            } else if (_2tars.find("type") != _2tars.end()) {
                stp = _2tars["type"];
            } else if (stp.find(",") != stp.npos || stp.find(" ") != stp.npos) {
                s << TAB << "using tp_" << pmbr->getId() << " = " << stp << ";" << endl;
                stp = "tp_" + pmbr->getId();
            } else if(stp.find("::") == stp.npos) {
                stp = _namespace + "::" + stp;
            }
            s << TAB << smacro << "(" << pmbr->getId() << ", " << ntag << ", " << stp << ");";
            if (!pmbr->getDesc().empty()) {
                s << " // " << pmbr->getDesc();
            }
        } else {
            s << TAB << tostr(pmbr->getTypePtr()) << " " << pmbr->getId() << toStrSuffix(pmbr) << ";";
        }
        s << endl;
    }
    if (_bMarkSupport) {
        DEL_TAB;
        s << TAB << "public:" << endl;
        INC_TAB;
        s << TAB << "tarsChgMark<" << (maxtag / (sizeof(uint64_t) * 8) + 1) << "> _chgmark;" << endl;
    }

    DEL_TAB;
    s << TAB << "};" << endl;

    //定义!=
    s << TAB << "inline bool operator!=(const " << pPtr->getId() << "&l, const " << pPtr->getId() << "&r) {" << endl;
    INC_TAB;
    s << TAB << "return !(l == r);" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    //定义 << >>
    if (_bJsonSupport) {
        //重载 <<
        s << TAB << "inline std::ostream& operator<<(std::ostream& os,const " << pPtr->getId() << "&r) {" << endl;
        INC_TAB;
        s << TAB << "os << r.writeToJsonString();" << endl;
        s << TAB << "return os;" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;

        //重载 >>
        s << TAB << "inline std::istream& operator>>(std::istream& is," << pPtr->getId() << "&l) {" << endl;
        INC_TAB;
        s << TAB << "std::istreambuf_iterator<char> eos;" << endl;
        s << TAB << "std::string s(std::istreambuf_iterator<char>(is), eos);" << endl;
        s << TAB << "l.readFromJsonString(s);" << endl;
        s << TAB << "return is;" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;
    }

    auto key = pPtr->getKey();
    //定义<
    if (key.size() > 0) {
        s << TAB << "inline bool operator<(const " << pPtr->getId() << "&l, const " << pPtr->getId() << "&r) {" << endl;
        INC_TAB;
        for (size_t i = 0; i < key.size(); i++) {
            s << TAB << "if(l." << key[i] << " != r." << key[i] << ") ";
            for (size_t z = 0; z < member.size(); z++) {
                if (key[i] == member[z]->getId() && (member[z]->getTypePtr()->isArray() || member[z]->getTypePtr()->isPointer())) { //数组类型、指针类型
                    s << "memcmp(l." << key[i] << ",r." << key[i] << ",l." << key[i] << "Len)< 0";
                }
            }
            s << " return (l." << key[i] << " < r." << key[i] << ");" << endl;
        }

        s << TAB << "return false;" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;

        //定义<=
        s << TAB << "inline bool operator<=(const " << pPtr->getId() << "&l, const " << pPtr->getId() << "&r) {" << endl;
        INC_TAB;
        s << TAB << "return !(r < l);" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;

        //定义>
        s << TAB << "inline bool operator>(const " << pPtr->getId() << "&l, const " << pPtr->getId() << "&r) {" << endl;
        INC_TAB;
        s << TAB << "return r < l;" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;

        //定义>=
        s << TAB << "inline bool operator>=(const " << pPtr->getId() << "&l, const " << pPtr->getId() << "&r) {" << endl;
        INC_TAB;
        s << TAB << "return !(l < r);" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;
    }
    return s.str();
}

/*******************************ContainerPtr********************************/
string Tars2Cpp::generateH(const ContainerPtr& pPtr) const {
    ostringstream s;
    for (size_t i = 0; i < pPtr->getAllNamespacePtr().size(); i++) {
        s << generateH(pPtr->getAllNamespacePtr()[i]) << endl;
        s << endl;
    }
    return s.str();
}

/******************************ParamDeclPtr***************************************/
string Tars2Cpp::generateH(const ParamDeclPtr& pPtr) const {
    ostringstream s;
    if (pPtr->isOut() || pPtr->getTypeIdPtr()->getTypePtr()->isSimple()) { // 输出参数, 或简单类型
        s << tostr(pPtr->getTypeIdPtr()->getTypePtr());
    } else { // 结构, map, vector, string
        s << "const " << tostr(pPtr->getTypeIdPtr()->getTypePtr()) << " &";
    }
    if (pPtr->isOut()) {
        s << " &";
    } else {
        s << " ";
    }
    s << pPtr->getTypeIdPtr()->getId();
    return s.str();
}

string Tars2Cpp::generateOutH(const ParamDeclPtr& pPtr) const {
    if (!pPtr->isOut()) {
        return "";
    }

    ostringstream s;
    if (pPtr->getTypeIdPtr()->getTypePtr()->isSimple()) { // 输出参数, 或简单类型
        s << tostr(pPtr->getTypeIdPtr()->getTypePtr()) << " ";
    } else { // 结构, map, vector, string
        s << "const " << tostr(pPtr->getTypeIdPtr()->getTypePtr()) << " &";
    }
    s << pPtr->getTypeIdPtr()->getId();
    return s.str();
}

string Tars2Cpp::generateParamDecl(const ParamDeclPtr& pPtr) const {
    ostringstream s;
    if (pPtr->isOut() || pPtr->getTypeIdPtr()->getTypePtr()->isSimple()) {
        s << tostr(pPtr->getTypeIdPtr()->getTypePtr());
        if (pPtr->isOut()) {
            s << " &";
        } else {
            s << " ";
        }
    } else { // 输入参数
        s << "const " << tostr(pPtr->getTypeIdPtr()->getTypePtr()) << " &";
    }
    s << pPtr->getTypeIdPtr()->getId();
    return s.str();
}

string Tars2Cpp::generateDispatchAsync(const OperationPtr& pPtr, const string& cn) const {
    ostringstream s;
    s << TAB << "if (msg->response->iRet != tars::TARSSERVERSUCCESS) {" << endl;

    INC_TAB;
    s << TAB << "callback_" << pPtr->getId() << "_exception(msg->response->iRet);" << endl;
    s << TAB << "return msg->response->iRet;" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;
    s << endl;

    s << TAB << _namespace + "::TarsInputStream<" + _namespace + "::BufferReader> _is;" << endl;
    s << TAB << "_is.setBuffer(msg->response->sBuffer);" << endl;

    //对输出参数编码
    if (pPtr->getReturnPtr()->getTypePtr()) {
        s << TAB << tostr(pPtr->getReturnPtr()->getTypePtr()) << " " << pPtr->getReturnPtr()->getId()
          << generateInitValue(pPtr->getReturnPtr()) << ";" << endl;
        s << readFrom(pPtr->getReturnPtr()) << endl;
    }

    auto& vParamDecl = pPtr->getAllParamDeclPtr();
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        if (vParamDecl[i]->isOut()) {
            s << TAB << tostr(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << " "
              << vParamDecl[i]->getTypeIdPtr()->getId() << generateInitValue(vParamDecl[i]->getTypeIdPtr()) << ";" << endl;
            s << readFrom(vParamDecl[i]->getTypeIdPtr());
        }
    }

    //处理线程私有数据
    s << TAB << "auto pCbtd = CallbackThreadData::getData();" << endl;
    s << TAB << "if(pCbtd) {" << endl;
    INC_TAB;
    s << TAB << "pCbtd->setResponseContext(msg->response->context);" << endl;

    //异步回调都无返回值
    s << TAB << "callback_" << pPtr->getId() << "(";
    string sParams;
    if (pPtr->getReturnPtr()->getTypePtr()) {
        sParams = pPtr->getReturnPtr()->getId() + ", ";
    }
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        if (vParamDecl[i]->isOut()) {
            sParams += vParamDecl[i]->getTypeIdPtr()->getId() + ", ";
        }
    }
    s << tars::TC_Common::trimright(sParams, ", ", false) <<  ");" << endl;

    s << TAB << "pCbtd->delResponseContext();" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    s << TAB << "return tars::TARSSERVERSUCCESS;" << endl;
    return s.str();
}

///////////////////////////////////////////////////////////////////////////////////////////////
string Tars2Cpp::generateDispatchCoroAsync(const OperationPtr& pPtr, const string& cn) const {
    ostringstream s;
    s << TAB << "if (msg->response->iRet != tars::TARSSERVERSUCCESS) {" << endl;

    INC_TAB;
    s << TAB << "callback_" << pPtr->getId() << "_exception(msg->response->iRet);" << endl;
    s << TAB << "return msg->response->iRet;" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;
    s << endl;
    s << TAB << _namespace + "::TarsInputStream<" + _namespace + "::BufferReader> _is;" << endl;
    s << TAB << "_is.setBuffer(msg->response->sBuffer);" << endl;

    auto& vParamDecl = pPtr->getAllParamDeclPtr();
    if (pPtr->getReturnPtr()->getTypePtr() || vParamDecl.size() > 0) {
        s << TAB << "try {" << endl;
        INC_TAB;
    }

    //对输出参数编码
    if (pPtr->getReturnPtr()->getTypePtr()) {
        s << TAB << tostr(pPtr->getReturnPtr()->getTypePtr()) << " " << pPtr->getReturnPtr()->getId()
          << generateInitValue(pPtr->getReturnPtr()) << ";" << endl;
        s << readFrom(pPtr->getReturnPtr()) << endl;
    }

    for (size_t i = 0; i < vParamDecl.size(); i++) {
        if (vParamDecl[i]->isOut()) {
            s << TAB << tostr(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << " "
              << vParamDecl[i]->getTypeIdPtr()->getId() << generateInitValue(vParamDecl[i]->getTypeIdPtr()) << ";" << endl;
            s << readFrom(vParamDecl[i]->getTypeIdPtr());
        }
    }

    s << TAB << "setResponseContext(msg->response->context);" << endl;

    //异步回调都无返回值
    s << TAB << "callback_" << pPtr->getId() << "(";
    string sParams;
    if (pPtr->getReturnPtr()->getTypePtr()) {
        sParams = pPtr->getReturnPtr()->getId() + ", ";
    }
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        if (vParamDecl[i]->isOut()) {
            sParams += vParamDecl[i]->getTypeIdPtr()->getId() + ", ";
        }
    }
    s << tars::TC_Common::trimright(sParams, ", ", false) <<  ");" << endl;

    if (pPtr->getReturnPtr()->getTypePtr() || vParamDecl.size() > 0) {
        DEL_TAB;

        s << TAB << "} catch(std::exception &ex) {" << endl;

        INC_TAB;
        s << TAB << "callback_" << pPtr->getId() << "_exception(tars::TARSCLIENTDECODEERR);" << endl;
        s << TAB << "return tars::TARSCLIENTDECODEERR;" << endl;
        DEL_TAB;

        s << TAB << "} catch(...) {" << endl;

        INC_TAB;
        s << TAB << "callback_" << pPtr->getId() << "_exception(tars::TARSCLIENTDECODEERR);" << endl;
        s << TAB << "return tars::TARSCLIENTDECODEERR;" << endl;
        DEL_TAB;

        s << TAB << "}" << endl;
    }

    s << TAB << "return tars::TARSSERVERSUCCESS;" << endl;
    return s.str();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
string Tars2Cpp::generateHAsync(const OperationPtr& pPtr) const {
    ostringstream s;
    auto& vParamDecl = pPtr->getAllParamDeclPtr();
    s << TAB << "virtual void " << "callback_" << pPtr->getId() << "(";

    string sParams;
    if (pPtr->getReturnPtr()->getTypePtr()) {
        if (pPtr->getReturnPtr()->getTypePtr()->isSimple()) {
            sParams = tostr(pPtr->getReturnPtr()->getTypePtr()) + " ret, ";
        } else { // 结构, map, vector, string
            sParams =  "const " + tostr(pPtr->getReturnPtr()->getTypePtr()) + "& ret, ";
        }
    }
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        auto& pPtr = vParamDecl[i];
        if (pPtr->isOut()) {
            if (pPtr->getTypeIdPtr()->getTypePtr()->isSimple()) { // 输出参数, 或简单类型
                sParams += tostr(pPtr->getTypeIdPtr()->getTypePtr());
            } else { // 结构, map, vector, string
                sParams += " const " + tostr(pPtr->getTypeIdPtr()->getTypePtr()) + "&";
            }
            sParams += " " + pPtr->getTypeIdPtr()->getId() + ", ";
        }
    }
    s << tars::TC_Common::trimright(sParams, ", ", false) << ") {" << endl;
    s << TAB << "    throw std::runtime_error(\"callback_" << pPtr->getId() << "() override incorrect.\");" << endl;
    s << TAB << "}" << endl;

    s << TAB << "virtual void " << "callback_" << pPtr->getId() << "_exception(" + _namespace + "::Int32 ret) {" << endl;
    s << TAB << "    throw std::runtime_error(\"callback_" << pPtr->getId() << "_exception() override incorrect.\");" << endl;
    s << TAB << "}" << endl;

    return s.str();
}

string Tars2Cpp::generateInitValue(const TypeIdPtr& pPtr) const {
    auto bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
    string init = "";
    if (bPtr && Builtin::KindBool == bPtr->kind()) {
        init = " = false";
    }

    //枚举强制类型转换在O2编译选项情况下会告警
    auto ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr());
    if (ePtr) {
        if (pPtr->hasDefault()) {
            auto sid = ePtr->getSid();
            init = " = " + pPtr->def() + ";";
        } else {
            auto& eMember = ePtr->getAllMemberPtr();
            if (eMember.size() > 0) {
                auto sid = ePtr->getSid();
                init = " = " + sid.substr(0, sid.find_first_of("::")) + "::" + eMember[0]->getId() + ";";
            }
        }
    }
    return init;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
string Tars2Cpp::generateServantDispatch(const OperationPtr& pPtr, const string& cn) const {
    ostringstream s;
    s << TAB << _namespace + "::TarsInputStream<" + _namespace + "::BufferReader> _is;" << endl;
    s << TAB << "_is.setBuffer(_current->getRequestBuffer());" << endl;

    string routekey;
    auto& vParamDecl = pPtr->getAllParamDeclPtr();
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        s << TAB << tostr(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << " " << vParamDecl[i]->getTypeIdPtr()->getId()
          << generateInitValue(vParamDecl[i]->getTypeIdPtr()) << ";" << endl;

        if (routekey.empty() && vParamDecl[i]->isRouteKey()) {
            routekey = vParamDecl[i]->getTypeIdPtr()->getId();
        }
    }

    s << TAB << "if (_current->getRequestVersion() == TUPVERSION) {" << endl;
    INC_TAB;
    s << TAB << "UniAttribute<" + _namespace + "::BufferWriterVector, " + _namespace + "::BufferReader>  tarsAttr;" << endl;
    s << TAB << "tarsAttr.setVersion(_current->getRequestVersion());" << endl;
    s << TAB << "tarsAttr.decode(_current->getRequestBuffer());" << endl;
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        auto sParamName =  vParamDecl[i]->getTypeIdPtr()->getId();
        string sEnum2Int = (EnumPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) ? "(" + _namespace + "::Int32)" : "";
        if (!vParamDecl[i]->isOut()) { // 枚举类型转成int
            if (EnumPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) {
                s << TAB << sParamName << " = (" << tostr(vParamDecl[i]->getTypeIdPtr()->getTypePtr())
                  << ") tarsAttr.get<" + _namespace + "::Int32>(\"" << sParamName << "\");" << endl;
            } else {
                s << TAB << "tarsAttr.get(\"" << sParamName << "\", " << sParamName << ");" << endl;
            }
        } else { // 枚举类型转成int
            if (EnumPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) {
                s << TAB << sParamName << " = (" << tostr(vParamDecl[i]->getTypeIdPtr()->getTypePtr())
                  << ") tarsAttr.getByDefault<" + _namespace + "::Int32>(\"" << sParamName << "\", " << sEnum2Int << sParamName << ");" << endl;
            } else {
                s << TAB << "tarsAttr.getByDefault(\"" << sParamName << "\", " << sEnum2Int << sParamName << ", "
                  << sEnum2Int << sParamName << ");" << endl;
            }
        }
    }
    DEL_TAB;
    s << TAB << "}" << endl;

    // 支持JSON协议分发
    if (_bJsonSupport) {
        s << TAB << "else if (_current->getRequestVersion() == JSONVERSION) {" << endl;
        INC_TAB;
        s << TAB << _namespace << "::JsonValueObjPtr _jsonPtr = " << _namespace << "::JsonValueObjPtr::dynamicCast(" << _namespace <<
          "::TC_Json::getValue(_current->getRequestBuffer()));" << endl;
        for (size_t i = 0; i < vParamDecl.size(); i++) {
            auto sParamName =  vParamDecl[i]->getTypeIdPtr()->getId();
            string sEnum2Int = (EnumPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) ? "(" + _namespace + "::Int32)" : "";
            if (!vParamDecl[i]->isOut()) {
                s << TAB << _namespace << "::JsonInput::readJson(" << sParamName << ", _jsonPtr->value[\"" << sParamName << "\"], true);" << endl;
            } else {
                s << TAB << _namespace << "::JsonInput::readJson(" << sParamName << ", _jsonPtr->value[\"" << sParamName << "\"], false);" << endl;
            }
        }
        DEL_TAB;
        s << TAB << "}" << endl;
    }

    s << TAB << "else {" << endl;
    INC_TAB;

    //普通tars请求
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        s << readFrom(vParamDecl[i]->getTypeIdPtr(), (!vParamDecl[i]->isOut()));
    }

    DEL_TAB;
    s << TAB << "}" << endl;

    if (pPtr->getReturnPtr()->getTypePtr()) {
        s << TAB << tostr(pPtr->getReturnPtr()->getTypePtr()) << " " << pPtr->getReturnPtr()->getId() << " = " << pPtr->getId() << "(";
    } else {
        s << TAB << pPtr->getId() << "(";
    }

    for (size_t i = 0; i < vParamDecl.size(); i++) {
        s << vParamDecl[i]->getTypeIdPtr()->getId();
        if (i != vParamDecl.size() - 1) {
            s << ",";
        } else {
            s << ", _current);" << endl;
        }
    }
    if (vParamDecl.size() == 0) {
        s << "_current);" << endl;
    }
    s << TAB << "if(_current->isResponse()) {" << endl;
    INC_TAB;

    s << TAB << "if (_current->getRequestVersion() == TUPVERSION) {" << endl;
    INC_TAB;

    s << TAB << "UniAttribute<" + _namespace + "::BufferWriterVector, " + _namespace + "::BufferReader>  tarsAttr;" << endl;
    s << TAB << "tarsAttr.setVersion(_current->getRequestVersion());" << endl;
    if (pPtr->getReturnPtr()->getTypePtr()) {
        string sEnum2Int = (EnumPtr::dynamicCast(pPtr->getReturnPtr()->getTypePtr())) ? "(" + _namespace + "::Int32)" : "";
        s << TAB << "tarsAttr.put(\"\", " << sEnum2Int << "_ret);" << endl;
        s << TAB << "tarsAttr.put(\"tars_ret\", " << sEnum2Int << "_ret);" << endl;
    }
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        auto sParamName = vParamDecl[i]->getTypeIdPtr()->getId();
        string sEnum2Int = (EnumPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) ? "(" + _namespace + "::Int32)" : "";
        if (vParamDecl[i]->isOut()) {
            s << TAB << "tarsAttr.put(\"" << sParamName << "\", " << sEnum2Int << sParamName << ");" << endl;
        }
    }
    s << TAB << "tarsAttr.encode(_sResponseBuffer);" << endl;

    DEL_TAB;
    s << TAB << "}" << endl;

    // 支持JSON协议分发
    if (_bJsonSupport) {
        s << TAB << "else if (_current->getRequestVersion() == JSONVERSION) {" << endl;
        INC_TAB;
        s << TAB << "auto _p = new " << _namespace << "::JsonValueObj();" << endl;
        for (size_t i = 0; i < vParamDecl.size(); i++) {
            auto sParamName =  vParamDecl[i]->getTypeIdPtr()->getId();
            if (vParamDecl[i]->isOut()) {
                s << TAB << "_p->value[\"" << sParamName << "\"] = " << _namespace << "::JsonOutput::writeJson(" << sParamName << ");" << endl;
            }
        }

        if (pPtr->getReturnPtr()->getTypePtr()) {
            s << TAB << "_p->value[\"tars_ret\"] = " << _namespace << "::JsonOutput::writeJson(_ret);" << endl;
        }

        s << TAB << _namespace << "::TC_Json::writeValue(_p, _sResponseBuffer);" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;
    }
    s << TAB << "else {" << endl;

    //普通tars调用输出参数
    INC_TAB;
    s << TAB << _namespace + "::TarsOutputStream<" + _namespace + "::BufferWriterVector> _os;" << endl;

    if (pPtr->getReturnPtr()->getTypePtr()) {
        s << writeTo(pPtr->getReturnPtr());
    }
    //解码输出参数
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        if (vParamDecl[i]->isOut()) {
            s << writeTo(vParamDecl[i]->getTypeIdPtr());
        }
    }
    s << TAB << "_os.swap(_sResponseBuffer);" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    s << TAB << "return tars::TARSSERVERSUCCESS;" << endl;
    return s.str();
}

string Tars2Cpp::generateHAsync(const OperationPtr& pPtr, const string& cn) const {
    ostringstream s;
    // 生成函数声明
    s << TAB << "void async_" << pPtr->getId() << "(";
    s << cn << "PrxCallbackPtr callback,";

    string routekey = "";
    auto& vParamDecl = pPtr->getAllParamDeclPtr();
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        if (!vParamDecl[i]->isOut()) {
            s << generateParamDecl(vParamDecl[i]) << ",";
        }
        if (routekey.empty() && vParamDecl[i]->isRouteKey()) {
            routekey = vParamDecl[i]->getTypeIdPtr()->getId();
        }
    }
    s << "const std::map<std::string, std::string>& context = TARS_CONTEXT()) {" << endl;
    INC_TAB;

    if (_tarsMaster) {
        s << TAB << "this->tars_setMasterFlag(true);" << endl;
    }
    s << TAB << _namespace + "::TarsOutputStream<" + _namespace + "::BufferWriterVector> _os;" << endl;

    for (size_t i = 0; i < vParamDecl.size(); i++) {
        if (vParamDecl[i]->isOut()) {
            continue;
        }
        s << writeTo(vParamDecl[i]->getTypeIdPtr());
    }
    s << TAB << "std::map<std::string, std::string> _mStatus;" << endl;

    if (!routekey.empty()) {
        ostringstream os;
        os << routekey;
        s << TAB << "_mStatus.insert(std::make_pair(ServantProxy::STATUS_GRID_KEY, " << os.str() << "));" << endl;
    }

    s << TAB << "tars_invoke_async(tars::TARSNORMAL,\"" << pPtr->getId() << "\", _os, context, _mStatus, callback);" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;
    s << TAB << endl;

    //协程并行异步的函数声明
    s << TAB << "void coro_" << pPtr->getId() << "(";
    s << cn << "CoroPrxCallbackPtr callback,";

    for (size_t i = 0; i < vParamDecl.size(); i++) {
        if (!vParamDecl[i]->isOut()) {
            s << generateParamDecl(vParamDecl[i]) << ",";
        }
    }
    s << "const std::map<std::string, std::string>& context = TARS_CONTEXT()) {" << endl;
    INC_TAB;

    if (_tarsMaster) {
        s << TAB << "this->tars_setMasterFlag(true);" << endl;
    }

    s << TAB << _namespace + "::TarsOutputStream<" + _namespace + "::BufferWriterVector> _os;" << endl;

    for (size_t i = 0; i < vParamDecl.size(); i++) {
        if (vParamDecl[i]->isOut()) {
            continue;
        }
        s << writeTo(vParamDecl[i]->getTypeIdPtr());
    }

    s << TAB << "std::map<std::string, std::string> _mStatus;" << endl;
    if (!routekey.empty()) {
        ostringstream os;
        os << routekey;
        s << TAB << "_mStatus.insert(std::make_pair(ServantProxy::STATUS_GRID_KEY, " << os.str() << "));" << endl;
    }
    s << TAB << "tars_invoke_async(tars::TARSNORMAL,\"" << pPtr->getId() << "\", _os, context, _mStatus, callback, true);" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    return s.str();
}

/////////////////////////////////////////////////////////////////////////////////////////////////
string Tars2Cpp::generateH(const OperationPtr& pPtr, bool bVirtual, const string& interfaceId) const {
    ostringstream s;
    s << TAB;

    if (bVirtual) {
        s << "virtual ";
    }
    s << tostr(pPtr->getReturnPtr()->getTypePtr()) << " " << pPtr->getId() << "(";

    string routekey = "";
    auto& vParamDecl = pPtr->getAllParamDeclPtr();
    for (size_t i = 0; i < vParamDecl.size(); i++) {
        s << generateH(vParamDecl[i]) << ",";
        if (routekey.empty() && vParamDecl[i]->isRouteKey()) {
            routekey = vParamDecl[i]->getTypeIdPtr()->getId();
        }
    }

    if (bVirtual) {
        s << "tars::TarsCurrentPtr current) = 0;";
    } else {
        s << "const std::map<std::string, std::string> &context = TARS_CONTEXT(), std::map<std::string, std::string> * pResponseContext = nullptr) {" << endl;
        INC_TAB;

        if (_tarsMaster) {
            s << TAB << "this->tars_setMasterFlag(true);" << endl;
        }
        s << TAB << _namespace + "::TarsOutputStream<" + _namespace + "::BufferWriterVector> _os;" << endl;

        for (size_t i = 0; i < vParamDecl.size(); i++) {
            s << writeTo(vParamDecl[i]->getTypeIdPtr());
        }
        s << TAB << "std::map<std::string, std::string> _mStatus;" << endl;

        if (!routekey.empty()) {
            ostringstream os;
            os << routekey;
            s << TAB << "_mStatus.insert(std::make_pair(ServantProxy::STATUS_GRID_KEY, " << os.str() << "));" << endl;
        }

        s << TAB << "std::shared_ptr<" + _namespace + "::ResponsePacket> rep = tars_invoke(tars::TARSNORMAL,\""
          << pPtr->getId() << "\", _os, context, _mStatus);" << endl;
        s << TAB << "if(pResponseContext) {" << endl;
        INC_TAB;
        s << TAB << "pResponseContext->swap(rep->context);" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;
        s << endl;

        if (vParamDecl.size() > 0 || pPtr->getReturnPtr()->getTypePtr()) {
            s << TAB <<  _namespace + "::TarsInputStream<" + _namespace + "::BufferReader> _is;" << endl;
            s << TAB << "_is.setBuffer(rep->sBuffer);" << endl;
            if (pPtr->getReturnPtr()->getTypePtr()) {
                s << TAB << tostr(pPtr->getReturnPtr()->getTypePtr()) << " " << pPtr->getReturnPtr()->getId()
                  << generateInitValue(pPtr->getReturnPtr()) << ";"  << endl;
                s << readFrom(pPtr->getReturnPtr());
            }
            for (size_t i = 0; i < vParamDecl.size(); i++) {
                if (vParamDecl[i]->isOut()) {
                    s << readFrom(vParamDecl[i]->getTypeIdPtr());
                }
            }
            if (pPtr->getReturnPtr()->getTypePtr()) {
                s << TAB << "return " << pPtr->getReturnPtr()->getId() << ";" << endl;
            }
        }
        DEL_TAB;
        s << TAB << "}" << endl;
    }
    s << endl;

    if (bVirtual) {
        //异步回调
        s << TAB << "static void async_response_" << pPtr->getId() << "(tars::TarsCurrentPtr current";
        if (pPtr->getReturnPtr()->getTypePtr()) {
            s << ", ";
            if (pPtr->getReturnPtr()->getTypePtr()->isSimple()) {
                s << tostr(pPtr->getReturnPtr()->getTypePtr()) << " ";
            } else { // 结构, map, vector, string
                s << "const " << tostr(pPtr->getReturnPtr()->getTypePtr()) << " &";
            }
            s << pPtr->getReturnPtr()->getId();
        }
        for (size_t i = 0; i < vParamDecl.size(); i++) {
            if (!vParamDecl[i]->isOut()) {
                continue;
            }
            s << ", ";
            s << generateOutH(vParamDecl[i]);
        }
        s << ") {" << endl;
        INC_TAB;

        s << TAB << "if (current->getRequestVersion() == TUPVERSION ) {" << endl;
        INC_TAB;

        s << TAB << "UniAttribute<" + _namespace + "::BufferWriterVector, " + _namespace + "::BufferReader>  tarsAttr;" << endl;
        s << TAB << "tarsAttr.setVersion(current->getRequestVersion());" << endl;
        if (pPtr->getReturnPtr()->getTypePtr()) {
            string sEnum2Int = (EnumPtr::dynamicCast(pPtr->getReturnPtr()->getTypePtr())) ? "(" + _namespace + "::Int32)" : "";
            s << TAB << "tarsAttr.put(\"\", " << sEnum2Int << "_ret);" << endl;
            s << TAB << "tarsAttr.put(\"tars_ret\", " << sEnum2Int << "_ret);" << endl;
        }
        for (size_t i = 0; i < vParamDecl.size(); i++) {
            auto sParamName = vParamDecl[i]->getTypeIdPtr()->getId();
            string sEnum2Int = (EnumPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) ? "(" + _namespace + "::Int32)" : "";
            if (vParamDecl[i]->isOut()) {
                s << TAB << "tarsAttr.put(\"" << sParamName << "\", " << sEnum2Int << sParamName << ");" << endl;
            }
        }
        s << endl;
        s << TAB << "std::vector<char> sTupResponseBuffer;" << endl;
        s << TAB << "tarsAttr.encode(sTupResponseBuffer);" << endl;
        s << TAB << "current->sendResponse(tars::TARSSERVERSUCCESS, sTupResponseBuffer);" << endl;

        DEL_TAB;
        s << TAB << "}" << endl;

        if (_bJsonSupport) {
            s << TAB << "else if (current->getRequestVersion() == JSONVERSION) {" << endl;
            INC_TAB;
            s << TAB << "auto _p = new " << _namespace << "::JsonValueObj();" << endl;
            for (size_t i = 0; i < vParamDecl.size(); i++) {
                auto sParamName = vParamDecl[i]->getTypeIdPtr()->getId();
                if (vParamDecl[i]->isOut()) {
                    s << TAB << "_p->value[\"" << sParamName << "\"] = " << _namespace << "::JsonOutput::writeJson(" << sParamName << ");" << endl;
                }
            }

            if (pPtr->getReturnPtr()->getTypePtr()) {
                s << TAB << "_p->value[\"tars_ret\"] = " << _namespace << "::JsonOutput::writeJson(_ret);" << endl;
            }

            s << TAB << "std::vector<char> sJsonResponseBuffer;" << endl;
            s << TAB << _namespace << "::TC_Json::writeValue(_p, sJsonResponseBuffer);" << endl;
            s << TAB << "current->sendResponse(tars::TARSSERVERSUCCESS, sJsonResponseBuffer);" << endl;
            DEL_TAB;
            s << TAB << "}" << endl;
        }

        s << TAB << "else {" << endl;
        INC_TAB;

        s << TAB <<  _namespace + "::TarsOutputStream<" + _namespace + "::BufferWriterVector> _os;" << endl;
        if (pPtr->getReturnPtr()->getTypePtr()) {
            s << writeTo(pPtr->getReturnPtr()) << endl;
        }
        for (size_t i = 0; i < vParamDecl.size(); i++) {
            if (!vParamDecl[i]->isOut()) {
                continue;
            }
            s << writeTo(vParamDecl[i]->getTypeIdPtr()) << endl;
        }
        s << TAB << "current->sendResponse(tars::TARSSERVERSUCCESS, _os.getByteBuffer());" << endl;

        DEL_TAB;
        s << TAB << "}" << endl;
        DEL_TAB;
        s << TAB << "}" << endl;
    }
    return s.str();
}

/**
 * 对接口名排序
 */
struct SortOperation {
    bool operator()(const OperationPtr& o1, const OperationPtr& o2) {
        return o1->getId() < o2->getId();
    }
};

/******************************InterfacePtr***************************************/
string Tars2Cpp::generateH(const InterfacePtr& pPtr, const NamespacePtr& nPtr) const {
    ostringstream s;

    auto& vOperation = pPtr->getAllOperationPtr();
    std::sort(vOperation.begin(), vOperation.end(), SortOperation());

    //生成异步回调Proxy
    s << TAB << "/* callback of async proxy for client */" << endl;
    s << TAB << "class " << pPtr->getId() << "PrxCallback: public tars::ServantProxyCallback {" << endl;
    s << TAB << "public:" << endl;
    INC_TAB;
    s << TAB << "virtual ~" << pPtr->getId() << "PrxCallback() {}" << endl;

    for (size_t i = 0; i < vOperation.size(); i++) {
        s << generateHAsync(vOperation[i]) << endl;
    }

    DEL_TAB;
    s << TAB << "public:" << endl;
    INC_TAB;
    s << TAB << "virtual const std::map<std::string, std::string>& getResponseContext() const {" << endl;
    INC_TAB;

    s << TAB << "auto pCbtd = CallbackThreadData::getData();" << endl;
    s << TAB << "if(!pCbtd || !pCbtd->getContextValid()) {" << endl;
    INC_TAB;
    s << TAB << "throw TC_Exception(\"cann't get response context\");" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;
    s << TAB << "return pCbtd->getResponseContext();" << endl;

    DEL_TAB;
    s << TAB << "}" << endl;
    s << endl;

    DEL_TAB;
    s << TAB << "public:" << endl;
    INC_TAB;

    s << TAB << "virtual int onDispatch(tars::ReqMessagePtr msg) {" << endl;

    //生成异步回调接口
    INC_TAB;
    string dname    = "__" + pPtr->getId() + "_all";
    string dispatch =  "static ::std::string " + dname;
    s << TAB << dispatch << "[] = {" << endl;
    INC_TAB;

    for (size_t i = 0; i < vOperation.size(); i++) {
        s << TAB << "\"" << vOperation[i]->getId() << "\"";
        if (i != vOperation.size() - 1) {
            s << ",";
        }
        s << endl;

    }
    DEL_TAB;
    s << TAB << "};" << endl;

    s << TAB << "auto r = equal_range(" << dname << ", " << dname << "+"
      << vOperation.size() << ", std::string(msg->request.sFuncName));" << endl;

    s << TAB << "if(r.first == r.second) { return tars::TARSSERVERNOFUNCERR; }" << endl;
    s << TAB << "switch(r.first - " << dname << ") {" << endl;
    INC_TAB;

    for (size_t i = 0; i < vOperation.size(); i++) {
        s << TAB << "case " << i << ": {" << endl;
        INC_TAB;

        s << generateDispatchAsync(vOperation[i], pPtr->getId()) << endl;

        DEL_TAB;
        s << TAB << "}" << endl;
    }

    DEL_TAB;
    s << TAB << "}" << endl;

    s << TAB << "return tars::TARSSERVERNOFUNCERR;" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    s << endl;

    DEL_TAB;
    s << TAB << "};" << endl;

    s << TAB << "typedef tars::TC_AutoPtr<" << pPtr->getId() << "PrxCallback> " << pPtr->getId() << "PrxCallbackPtr;" << endl;
    s << endl;

    //生成协程异步回调类，用于并发请求
    s << TAB << "/* callback of coroutine async proxy for client */" << endl;
    s << TAB << "class " << pPtr->getId() << "CoroPrxCallback: public " << pPtr->getId() << "PrxCallback {" << endl;
    s << TAB << "public:" << endl;
    INC_TAB;
    s << TAB << "virtual ~" << pPtr->getId() << "CoroPrxCallback(){}" << endl;
    DEL_TAB;

    s << TAB << "public:" << endl;

    INC_TAB;
    s << TAB << "virtual const std::map<std::string, std::string>& getResponseContext() const { return _mRspContext; }" << endl;
    s << endl;
    s << TAB << "virtual void setResponseContext(const std::map<std::string, std::string>& mContext) { _mRspContext = mContext; }" << endl;
    s << endl;
    DEL_TAB;

    s << TAB << "public:" << endl;

    INC_TAB;
    //生成协程异步回调接口
    s << TAB << "int onDispatch(tars::ReqMessagePtr msg) {" << endl;
    INC_TAB;
    dname    = "__" + pPtr->getId() + "_all";
    dispatch =  "static ::std::string " + dname;
    s << TAB << dispatch << "[] = {" << endl;
    INC_TAB;

    for (size_t i = 0; i < vOperation.size(); i++) {
        s << TAB << "\"" << vOperation[i]->getId() << "\"";
        if (i != vOperation.size() - 1) {
            s << ",";
        }
        s << endl;
    }

    DEL_TAB;
    s << TAB << "};" << endl;

    s << endl;

    s << TAB << "auto r = equal_range(" << dname << ", " << dname << "+"
      << vOperation.size() << ", std::string(msg->request.sFuncName));" << endl;

    s << TAB << "if(r.first == r.second) return tars::TARSSERVERNOFUNCERR;" << endl;

    s << TAB << "switch(r.first - " << dname << ") {" << endl;
    INC_TAB;

    for (size_t i = 0; i < vOperation.size(); i++) {
        s << TAB << "case " << i << ": {" << endl;
        INC_TAB;

        s << generateDispatchCoroAsync(vOperation[i], pPtr->getId()) << endl;

        DEL_TAB;
        s << TAB << "}" << endl;
    }

    DEL_TAB;
    s << TAB << "}" << endl;

    s << TAB << "return tars::TARSSERVERNOFUNCERR;" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    s << endl;

    ////////////////////////////////////////////////////////////////////
    DEL_TAB;
    s << TAB << "protected:" << endl;

    INC_TAB;
    s << TAB << "std::map<std::string, std::string> _mRspContext;" << endl;
    DEL_TAB;

    s << TAB << "};" << endl;

    s << TAB << "typedef tars::TC_AutoPtr<" << pPtr->getId() << "CoroPrxCallback> " << pPtr->getId() << "CoroPrxCallbackPtr;" << endl;
    s << endl;

    //生成客户端代理
    s << TAB << "/* proxy for client */" << endl;
    s << TAB << "class " << pPtr->getId() << "Proxy : public tars::ServantProxy {" << endl;
    s << TAB << "public:" << endl;
    INC_TAB;
    s << TAB << "typedef std::map<std::string, std::string> TARS_CONTEXT;" << endl;

    for (size_t i = 0; i < vOperation.size(); i++) {
        s << generateH(vOperation[i], false, pPtr->getId()); // << endl;
        s << generateHAsync(vOperation[i], pPtr->getId()) << endl;
    }

    s << TAB << pPtr->getId() << "Proxy* tars_hash(int64_t key) {" << endl;
    INC_TAB;
    s << TAB << "return (" << pPtr->getId() + "Proxy*)ServantProxy::tars_hash(key);" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;
    s << endl;

    s << TAB << pPtr->getId() << "Proxy* tars_consistent_hash(int64_t key) {" << endl;
    INC_TAB;
    s << TAB << "return (" << pPtr->getId() + "Proxy*)ServantProxy::tars_consistent_hash(key);" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;
    s << endl;

    s << TAB << pPtr->getId() << "Proxy* tars_set_timeout(int msecond) {" << endl;
    INC_TAB;
    s << TAB << "return (" << pPtr->getId() + "Proxy*)ServantProxy::tars_set_timeout(msecond);" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;
    s << endl;

    s << TAB << "static const char* tars_prxname() { return \"" << pPtr->getId() << "Proxy\"; }" << endl;

    DEL_TAB;
    s << TAB << "};" << endl;

    s << TAB << "typedef tars::TC_AutoPtr<" << pPtr->getId() << "Proxy> " << pPtr->getId() << "Prx;" << endl;
    s << endl;

    //生成服务端Servant
    s << TAB <<  "/* servant for server */" << endl;
    s << TAB << "class " << pPtr->getId() << " : public tars::Servant {" << endl;
    s << TAB << "public:" << endl;
    INC_TAB;
    s << TAB << "virtual ~" << pPtr->getId() << "(){}" << endl;

    for (size_t i = 0; i < vOperation.size(); i++) {
        s << generateH(vOperation[i], true, pPtr->getId()) << endl;
    }

    DEL_TAB;
    s << TAB << "public:" << endl;
    INC_TAB;

    s << TAB << "int onDispatch(tars::TarsCurrentPtr _current, std::vector<char>& _sResponseBuffer) {" << endl;
    INC_TAB;
    dname    = "__" + nPtr->getId() + "__" + pPtr->getId() + "_all";
    dispatch =  "static ::std::string " + dname;
    s << TAB << dispatch << "[] = {" << endl;
    INC_TAB;

    for (size_t i = 0; i < vOperation.size(); i++) {
        s << TAB << "\"" << vOperation[i]->getId() << "\"";
        if (i != vOperation.size() - 1) {
            s << ",";
        }
        s << endl;
    }

    DEL_TAB;
    s << TAB << "};" << endl;

    s << endl;

    s << TAB << "auto r = equal_range(" << dname << ", " << dname << "+"
      << vOperation.size() << ", _current->getFuncName());" << endl;

    s << TAB << "if(r.first == r.second) { return tars::TARSSERVERNOFUNCERR; }" << endl;

    s << TAB << "switch(r.first - " << dname << ") {" << endl;
    INC_TAB;

    for (size_t i = 0; i < vOperation.size(); i++) {
        s << TAB << "case " << i << ": {" << endl;
        INC_TAB;

        s << generateServantDispatch(vOperation[i], pPtr->getId()) << endl;

        DEL_TAB;
        s << TAB << "}" << endl;
    }

    DEL_TAB;
    s << TAB << "}" << endl;

    s << TAB << "return tars::TARSSERVERNOFUNCERR;" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    DEL_TAB;
    s << TAB << "};" << endl;

    return s.str();
}

/******************************EnumPtr***************************************/

string Tars2Cpp::generateH(const EnumPtr& pPtr) const {
    ostringstream s;
    s << TAB << "enum " << pPtr->getId() << " {" << endl;

    INC_TAB;
    auto& member = pPtr->getAllMemberPtr();
    for (size_t i = 0; i < member.size(); i++) {
        s << TAB << member[i]->getId();
        if (member[i]->hasDefault()) {
            s << " = " << member[i]->def();
        }
        s << "," << endl;
    }
    DEL_TAB;
    s << TAB << "};" << endl;

    // 生成枚举转字符串函数
    s << TAB << "inline std::string etos" << "(const " <<  pPtr->getId() << "& e) {" << endl;
    INC_TAB;

    s << TAB << "switch(e) {" << endl;
    INC_TAB;

    for (size_t i = 0; i < member.size(); i++) {
        s << TAB << "case " <<  member[i]->getId() << ": return "
          << "\"" << member[i]->getId() << "\";" << endl;
    }
    s << TAB << "default: return \"\";" << endl;

    DEL_TAB;
    s << TAB << "}" << endl;
    DEL_TAB;
    s << TAB << "}" << endl;

    // 生成字符串转枚举函数
    s << TAB << "inline int stoe" << "(const std::string& s, " <<  pPtr->getId() << "& e) {" << endl;
    INC_TAB;

    for (size_t i = 0; i < member.size(); i++) {
        s << TAB << "if(s == \"" << member[i]->getId() << "\")  { e = " << member[i]->getId() << "; return 0; }" << endl;
    }
    s << TAB << "return -1;" << endl;

    DEL_TAB;
    s << TAB << "}" << endl;

    // 生成tars_clear方法
    s << TAB << "inline void tars_clear(" << pPtr->getId() << "& val) {" << endl;
    INC_TAB;
    auto& eMember = pPtr->getAllMemberPtr();
    if (eMember.size() > 0) {
        auto sid = pPtr->getSid();
        s << TAB << "val = " << sid.substr(0, sid.find_first_of("::")) << "::" << eMember[0]->getId() << ";" << endl;
    }
    DEL_TAB;
    s << TAB << "}" << endl;

    return s.str();
}

/******************************ConstPtr***************************************/
string Tars2Cpp::generateH(const ConstPtr& pPtr) const {
    ostringstream s;

    if (pPtr->getConstGrammarPtr()->t == ConstGrammar::STRING) {
        string tmp = tars::TC_Common::replace(pPtr->getConstGrammarPtr()->v, "\"", "\\\"");
        s << TAB << "const " << tostr(pPtr->getTypeIdPtr()->getTypePtr()) << " " << pPtr->getTypeIdPtr()->getId() << " = \"" << tmp << "\";" << endl;
    } else {
        s << TAB << "const " << tostr(pPtr->getTypeIdPtr()->getTypePtr()) << " " << pPtr->getTypeIdPtr()->getId() << " = " << pPtr->getConstGrammarPtr()->v
          << ((tostr(pPtr->getTypeIdPtr()->getTypePtr()) ==  _namespace + "::Int64") ? "LL;" : ";") << endl;
    }

    return s.str();
}
/******************************NamespacePtr***************************************/

string Tars2Cpp::generateH(const NamespacePtr& pPtr) const {
    ostringstream s;
    auto& is = pPtr->getAllInterfacePtr();
    auto& ss = pPtr->getAllStructPtr();
    auto& es = pPtr->getAllEnumPtr();
    auto& cs = pPtr->getAllConstPtr();

    s << endl;
    s << TAB << "namespace " << pPtr->getId() << " {" << endl;
    INC_TAB;

    for (size_t i = 0; i < cs.size(); i++) {
        s << generateH(cs[i]) << endl;
    }

    for (size_t i = 0; i < es.size(); i++) {
        s << generateH(es[i]) << endl;
    }

    for (size_t i = 0; i < ss.size(); i++) {
        s << generateH(ss[i], pPtr->getId()) << endl;
    }

    s << endl;

    for (size_t i = 0; i < is.size() && _onlyStruct == false; i++) {
        s << generateH(is[i], pPtr) << endl;
        s << endl;
    }

    DEL_TAB;
    s << "}";

    s << endl << endl;

    return s.str();
}


void Tars2Cpp::generateH(const ContextPtr& pPtr) const {
    auto n = g_parse->getFileName(pPtr->getFileName());
    auto fileH = g_parse->getAbsoluteFileName(_baseDir, g_parse->replaceFileName(n, "h"));
    auto fileCpp = g_parse->getAbsoluteFileName(_baseDir, g_parse->replaceFileName(n, "cpp"));

    ostringstream s;
    s << g_parse->printHeaderRemark();

    s << "#pragma once" << endl;
    s << endl;
    s << "#include <map>" << endl;
    s << "#include <string>" << endl;
    s << "#include <vector>" << endl;
    s << "#include \"tup/Tars.h\"" << endl;
    if (_bJsonSupport) {
        s << "#include \"tup/TarsJson.h\"" << endl;
    }
    if (!_vSIncIntf.empty()) {
        for (auto& intf : _vSIncIntf) {
            if (!intf.empty()) {
                s << "#include \"" << intf << "\"" << endl;
            }
        }
    }

    auto include = pPtr->getIncludes();
    for (size_t i = 0; i < include.size(); i++) {
        s << "#include \"" << g_parse->getHeader() << tars::TC_File::extractFileName(include[i]) << "\"" << endl;
    }

    //名字空间有接口
    auto namespaces = pPtr->getNamespaces();
    for (size_t i = 0; i < namespaces.size() && _onlyStruct == false; i++) {
        if (namespaces[i]->hasInterface()) {
            s << "#include \"servant/ServantProxy.h\"" << endl;
            s << "#include \"servant/Servant.h\"" << endl;
            break;
        }
    }
    s << endl;

    for (size_t i = 0; i < namespaces.size(); i++) {
        s << generateH(namespaces[i]) << endl;
    }

    s << endl;

    tars::TC_File::makeDirRecursive(_baseDir);
    tars::TC_File::save2file(fileH, s.str(), true);
}

void Tars2Cpp::createFile(const string& file) { //, const vector<string>& vsCoder)
    auto contexts = g_parse->getContexts();
    for (size_t i = 0; i < contexts.size(); i++) {
        if (file == contexts[i]->getFileName()) {
            generateH(contexts[i]);
        }
    }
}

StructPtr Tars2Cpp::findStruct(const ContextPtr& pPtr, const string& id) {
    auto sid = id;
    //在当前namespace中查找
    auto namespaces = pPtr->getNamespaces();
    for (size_t i = 0; i < namespaces.size(); i++) {
        auto np = namespaces[i];
        auto structs = np->getAllStructPtr();
        for (size_t i = 0; i < structs.size(); i++) {
            if (structs[i]->getSid() == sid) {
                return structs[i];
            }
        }
    }
    return nullptr;
}
